package dk.itu.samd.group2.tagapastry;

import java.util.Vector;

import dk.itu.samd.group2.tagapastry.messages.IndexExpansionMsg;
import dk.itu.samd.group2.tagapastry.messages.IndexMsg;
import dk.itu.samd.group2.tagapastry.messages.IndexRetractionRequestMsg;
import dk.itu.samd.group2.tagapastry.messages.TagapastryMsg;

public class IndexRelativeImpl implements IndexRelative {

	private Tag tag;
	private Vector<TagapastryMsg> msgBuffer;
	private State state;
	
	public IndexRelativeImpl(Tag tag, State state) {
		this.tag = tag;
		this.msgBuffer = new Vector<TagapastryMsg>();
		this.state = state;
	}

	@Override
	public Vector<TagapastryMsg> getMsgBuffer() {
		return msgBuffer;
	}

	public Tag getTag() {
		return this.tag;
	}

	public void bufferOrForward(IndexMsg msg, TagapastryImpl tagaImpl) {
		switch (state) {
		case ACTIVE:
//			System.out.println("sending: " + msg);
			tagaImpl.send(msg);
			break;
		case INACTIVE:
//			System.out.println("buffering: " + msg);
			if (msg.indexCreator()) {
				state = State.AWAITING_EXPANSION_CONFIRMATION;
				tagaImpl.send(msg);
			}
			break;
		case AWAITING_RETERACTION_CONFIRMATION:
		case AWAITING_EXPANSION_CONFIRMATION:
			msgBuffer.add(msg);
			break;
		}
	}

	@Override
	public void activate(TagapastryImpl tagaImpl) {
		state = State.ACTIVE;
		//System.out.println("sending buffered msges");
		for (TagapastryMsg msg : msgBuffer) {
			//System.out.println("  " + msg);
			tagaImpl.send(msg);
		}
		
		msgBuffer.clear();
	}


	@Override
	public void expand(TagapastryImpl tagaImpl, Vector<IndexEntry> entries) {
		state = State.AWAITING_EXPANSION_CONFIRMATION;
		IndexExpansionMsg msg = new IndexExpansionMsg(tag, tagaImpl.getNodeHandle(), entries);
//		for (IndexEntry entry : entries)
//			System.out.println("  expanding " + tag.getExtension()+": " + entry);
		tagaImpl.send(msg);
	}

	@Override
	public void retract(TagapastryImpl tagaImpl) {
		IndexRetractionRequestMsg msg = new IndexRetractionRequestMsg(tag, tagaImpl.getNodeHandle());

		switch (state) {
		case AWAITING_EXPANSION_CONFIRMATION:
			state = State.AWAITING_RETERACTION_CONFIRMATION;
			// TODO transfer buffered messages from this to index
			msgBuffer.add(msg);
			break;
		case ACTIVE:
			state = State.AWAITING_RETERACTION_CONFIRMATION;
			tagaImpl.send(msg);
			break;
		}
	
	}

	@Override
	public void deactivate() {
		state = State.INACTIVE;
		
	}

	@Override
	public boolean isInactive() {
		return state == State.INACTIVE;
	}	
	
	@Override
	public String toString() {
		return "{tag: " + tag + " }";
	}
	
	@Override
	public int getSize() {
		return tag.getSize();
	}

}
